'''
Created on 02/06/2014

@author: Vitor, Monique
'''
from funcoesAuxiliares.embaralhadores import embaralhaListas

'''
Esta função configura as variaveis omega e teta de forma a fazer a rede neural ter o maior numero de acertos possiveis

vetorEntradas = lista de entradas da rede neural

Obs.: o primeiro elemento da lista deve ser uma string, com alguma observação, portante este nao será utilizado nos
cálculos, os outros elementos devem ser inteiros

omega = lista de omegas iniciais
teta = valor de teta inicial(aconselha-se usar omega[0])
yDesejado = lista de yDesejados
f = funcao utilizada para calculo de y
tol = precisao do erro(default: 0.1)
passo = taxa de aprendizado(default: 0.1)

Obs.: esta função não está otimizada, portanto, o passo utilizado será o mesmo até o final do treinamento
'''
def delta(vetorEntradas, omega,  teta, yDesejado, f, tol = 0.1, passo = 0.1):
    numEntradas = len(vetorEntradas)
    erroTotal = 5
    listaErros = []
    it = 0
    
    '''
    Critério de parada:
    '''
    while erroTotal > tol and it < 10000:
        erroTotal = 0
        #yEncontrado = 0
        
        '''
        Embaralha os elementos da lista
        '''
        vetorEntradas, yDesejado = embaralhaListas(vetorEntradas, yDesejado)
        
        #print("\n\n----------------------------------------------------------------")
        #print("\nIteração " + str(it) + ":")
        
        for i in range(numEntradas):
            '''
            Calculo do yEncontrado
            '''
            yEncontrado = 0
            for j in range(len(omega)):
                yEncontrado += omega[j]*int(vetorEntradas[i][j+1])
            yEncontrado -= teta
            
            #print("\nyDesejado de " + vetorEntradas[i][0] + ": " + str(yDesejado[i]))
            #print("yEncontrado de " + vetorEntradas[i][0] + ": " + str(yEncontrado))
            
            '''
            Aplicando a função f
            '''
            yEncontrado = f(yEncontrado)
            
            #print("F() de " + vetorEntradas[i][0] + ": " + str(yEncontrado))
            
            '''
            Cálculo do Erro
            '''
            erro = yEncontrado - yDesejado[i]
            
            #print("Erro de " + vetorEntradas[i][0] + ": " + str(abs(erro)))
            '''
            o erro total deve ser contabilizado como um valor positivo sempre
            '''
            erroTotal += abs(erro)
            
            '''
            Cálculo de novos omegas
            '''
            for j in range(len(omega)):
                deltaOmega = passo*erro*int(vetorEntradas[i][j+1])
                omega[j] -= deltaOmega
            
            '''
            Cálculo de novo teta
            '''
            deltaTeta = passo*erro
            teta += deltaTeta
        
        '''
        acrescentando o erro na lista, para fazer checagem de curva de aprendizado
        '''
        listaErros.append(erroTotal)
        
        #print("\nLista Nova de Omegas:")
        #print(omega)
        
        #print("\nNovo Teta: " + str(teta))
        
        #print("\nErro Total " + str(it) + ": " + str(erroTotal))
        it += 1
        
    print("\n\nTotal de Iterações: " + str(it))
    
    return omega, teta, listaErros